package gps.monitor.common.tools.network;

import gps.monitor.common.core.network.*;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;

/**
 * @author cyq
 * @date 2021/11/4
 * @desc talk is cheep,show me the code
 */
public final class SimpleNettyServer implements ISocketServer {

    private SimpleNettyConnectConfig connectionConfig;

    private EventLoopGroup bossGroup;
    //Worker线程
    private EventLoopGroup workerGroup;

    private ChannelHandler decoder;

    private ChannelHandler handler;

    private ChannelFuture worker;


    protected SimpleNettyServer(SimpleNettyConnectConfig config, ChannelHandler decoder, ChannelHandler handler) {
        this.connectionConfig = config;
        this.decoder = decoder;
        this.handler = handler;
    }

    public void start() throws NetworkException {

        if (connectionConfig == null) throw new NetworkException("缺少配置：SimpleNettyConnectConfig");
        if (connectionConfig.getLitsenPort() < 1000) throw new NetworkException("监听端口litsenPort必须大于1000");

        bossGroup = new NioEventLoopGroup();
        workerGroup = new NioEventLoopGroup();

        try {

            //1.创建服务器对象
            ServerBootstrap bootstrap = new ServerBootstrap();
            //2.配置参数
            bootstrap.group(bossGroup,workerGroup)
                    //主线程处理类，底层用的是反射
                    .channel(NioServerSocketChannel.class)
                    //子线程处理类
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        public void initChannel(SocketChannel ch) throws Exception {
                            //无锁化串行编程
                            //Nerry对HTTP的封装，对顺序有要求
                            //对于inbound先add的先执行，而outbound则正好相反
                            ChannelPipeline pipeline = ch.pipeline();
                            //pipeline.addLast(new HttpClientCodec());
                            //pipeline.addLast(new HttpObjectAggregator(65536));
                            pipeline.addLast(decoder);
                            pipeline.addLast(handler);
                        }
                    })
                    //针对主线程的配置，最大分配128个线程
                    .option(ChannelOption.SO_BACKLOG, connectionConfig.getSoBackLog())
                    //针对子线程的配置，保持长连接
                    .childOption(ChannelOption.SO_KEEPALIVE,true);

            //3.启动服务器
            worker = bootstrap.bind(connectionConfig.getLitsenPort()).sync();
            //等待服务端口关闭
            //worker.channel().closeFuture();
        }catch (Exception e){
            e.printStackTrace();
            throw new NetworkException(e);
        }finally {
            //关闭线程池
            //bossGroup.shutdownGracefully();
            //关闭线程池
            //workerGroup.shutdownGracefully();
            System.out.println("Server启动完成");
        }
    }

    public void close() throws NetworkException {

        if (bossGroup == null) return;

        worker.channel().close();
        //关闭线程池
        bossGroup.shutdownGracefully();
        //关闭线程池
        workerGroup.shutdownGracefully();
    }
}
